from web3 import Web3
import time
import base64
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
import pickle

decrypt = ''
account_address = '0xbDcB2416e02b9e4f7714D6546606af08764852D2'
oracle_address = '0xac9548E2496d65B9D6fcb0f2158c20f2E63D1836'
oracle_contract = ''
w3 = ''

def handle_logdata(logdata):
    global decrypt
    global account_address
    global oracle_contract
    global w3
    logdata = logdata[2:]
    requester_address = Web3.toChecksumAddress(Web3.toHex(hexstr=logdata[(192+24):256]))
    identifier_address = Web3.toChecksumAddress(Web3.toHex(hexstr=logdata[(256+24):320]))
    publickey_len = Web3.toInt(hexstr=logdata[320:384])*2
    publickey = Web3.toText(hexstr=logdata[384:(384+publickey_len)])
    offset = 64-publickey_len%64
    encrypted_len = Web3.toInt(hexstr=logdata[(384+publickey_len+offset):(384+publickey_len+offset+64)])*2
    encrypted = Web3.toText(hexstr=logdata[(384+publickey_len+offset+64):(384+publickey_len+offset+64+encrypted_len)])
    encrypted_bytes = base64.b64decode(encrypted)
    decrypted_message = decrypt.decrypt(encrypted_bytes)
    pu_key = RSA.import_key(publickey)
    cipher = PKCS1_OAEP.new(key=pu_key)
    cipher_text = base64.b64encode(cipher.encrypt(decrypted_message))
    print("Requester:{}\nIdentifier:{}\nPublicKey:{}\nEncrypted:{}\nDecrypted:{}\nNew Encrypted:{}".format(requester_address, identifier_address, publickey, encrypted, decrypted_message, cipher_text))
    w3.geth.personal.unlockAccount(account_address, 'abc12345')
    oracle_contract.functions.callback(cipher_text, requester_address, identifier_address).transact(transaction={'gas': 2100000})

def log_loop(event_filter, poll_interval):
    while True:
        for event in event_filter.get_new_entries():
            if 'data' in event:
                handle_logdata(event['data'])
        time.sleep(poll_interval)

def main():
    global decrypt
    global account_address
    global oracle_address
    global oracle_contract
    global w3
    with open('oracle_prikey.pem', 'r') as f:
        private_pem = f.read()
    pr_key = RSA.import_key(private_pem)
    decrypt = PKCS1_OAEP.new(key=pr_key)
    w3 = Web3(Web3.IPCProvider('data/geth.ipc'))
    w3.eth.default_account = account_address
    with open('oracle_abi', 'rb') as f:
        oracle_abi = pickle.loads(f.read())
    oracle_contract = w3.eth.contract(address=oracle_address, abi=oracle_abi)
    block_filter = w3.eth.filter({'fromBlock':0, 'address':oracle_address})
    log_loop(block_filter, 2)

if __name__ == '__main__':
    main()